Level 0 | Level 1 | Level 2 | Level 3 | Level 4 |
Level 5 | Level 6 | Level 7 | Level 8 | Level 9 |
Level 10 | Level 11 | Level 12 | Level 13 | Level 14 |
LEVEL 8 Chunsoft Tetris 2 + Bombliss
Wow the music in the game is super cool and that's because the music was composed by Koichi Sugiyama, the same guy that made
Dragon Warrior/Dragon Quest music. This game is mapper 1 and so it's like mapper 2 in a lot of ways that we already worked
with. $8000 - $BFFF is where the 16K banks are switched in and out. $C000 - $FFFF is the hardwired section of the game. The
upper 16K which is the hardwired bank is what you could call the framework of the rom and calls the banks for different
levels,music driver,takes care of the interrupts and anything else. As you read here in this doc and The NES Music Ripping
Guide that the entry point to the play will be found in the NMI and so this is right and is found in the hardwired bank and
so is the entry point to the init but you can't find it because it's using an indirect routine which is a real pain to find
even if you're experienced. You can use nes2nsf and get the right bank which is 005 in the rom. However your best bet is to
use an emulator and dump $8000 - $FFFF because you need to disassemble the entire space to find the entry to the init code.
Indirect jump code is difficult to find like I say. However you need to understand it first to be able to find it. JMP
($xxxx) is Jump Indirect. You don't jump to the address in the parentheses you read the bytes at that address and you flip
the bytes around for your address to jump to. Usually these bytes are in PRG somewhere, you have to initialize these
addresses before you can make the indirect jump so you load 2 data pointers into the address stated in the indirect jump and
then you run the operation. A lot of games use this method. This game uses a slightly different method and is the same in
principle.
You have a code routine that is used many times for many different things. What you do is allocate code in zero page area of
memory and you JSR to the WRAM area and then JMP to another routine. It's different in that you don't use a JMP indirect
operation. I will paste the following code for you and you can check it out. This is the indirect routine.
$CEAF:85 20 STA $20 = #$B8 $CEB1:86 21 STX $21 = #$01 $CEB3:AD 04 03 LDA $0304 = #$05 $CEB6:48 PHA $CEB7:08 PHP $CEB8:AD 04 03 LDA $0304 = #$05 $CEBB:8D 15 03 STA $0315 = #$04 $CEBE:20 DE CE JSR $CEDE ; go to initializaton $CEC1:A9 4C LDA #$4C ; initialize JMP op $CEC3:85 23 STA $23 = #$4C ; " " " $CEC5:A6 21 LDX $21 = #$01 $CEC7:A5 20 LDA $20 = #$B8 $CEC9:28 PLP $CECA:20 23 00 JSR $0023 ; indirect
$0023:4C 42 89 JMP $8942 ; init code
This code might be confusing at first until you understand it. Addresses $23,$24,$25 are initialized somewhere, $23 is
initialized in this routine. You JSR(Jump Save Return) to address $0023 and execute the code that was initialized there in
WRAM. In this case the code leads you right to the init routine.
You might want to know how I found it. It was all guess work for the most part. I always check all the interrupts. In this
case I checked the BRK/IRQ interrupt and did an address break for $CF2C. I checked zero page for code and sure enough I ran
into some code in this area. I kept debugging this code at different times to see if I would run into the init code and sure
enough I did.
You know the drill, as always arrange your tunes. Count your tunes and fill in the composer and company names in the header.
After all this have fun listening to the rip. The addresses should be 8000/8942/8000 load/init/play respectively.